// Copyright (c) Corporation for National Research Initiatives
package org.python.util;
import java.io.File;
import java.io.InputStream;
import java.nio.charset.Charset;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import org.python.core.FileUtil;
import org.python.core.Options;
import org.python.core.Py;
import org.python.core.PyCode;
import org.python.core.PyException;
import org.python.core.PyModule;
import org.python.core.PyObject;
import org.python.core.PyString;
import org.python.core.PyStringMap;
import org.python.core.PySystemState;
import org.python.core.imp;
public class jython {
private static String usage = "usage: jython [options] [-jar jar | -c cmd | file | -] [args]\n"
+ "Options and arguments:\n" + "-i : inspect interactively after running script, and force\n"
+ " prompts, even if stdin does not appear to be a " + "terminal\n"
+ "-S : don't imply `import site' on initialization\n"
+ "-v : verbose (trace import statements)\n" + "-Dprop=v : Set the property `prop' to value `v'\n"
+ "-jar jar : program read from __run__.py in jar file\n"
+ "-c cmd : program passed in as string (terminates option list)\n"
+ "-W arg : warning control (arg is action:message:category:module:" + "lineno)\n"
+ "-E codec : Use a different codec the reading from the console.\n"
+ "-Q arg : division options: -Qold (default), -Qwarn, -Qwarnall, " + "-Qnew\n"
+ "file : program read from script file\n"
+ "- : program read from stdin (default; interactive mode if a " + "tty)\n"
+ "--help : print this usage message and exit\n" + "--version: print Jython version number and exit\n"
+ "args : arguments passed to program in sys.argv[1:]";
public static void runJar(String filename) {
// TBD: this is kind of gross because a local called `zipfile' just
// magically shows up in the module's globals. Either `zipfile'
// should be called `__zipfile__' or (preferrably, IMO), __run__.py
// should be imported and a main() function extracted. This
// function should be called passing zipfile in as an argument.
//
// Probably have to keep this code around for backwards
// compatibility (?)
try {
ZipFile zip = new ZipFile(filename);
ZipEntry runit = zip.getEntry("__run__.py");
if (runit == null)
throw Py.ValueError("jar file missing '__run__.py'");
PyStringMap locals = new PyStringMap();
// Stripping the stuff before the last File.separator fixes Bug
// #931129 by keeping illegal characters out of the generated
// proxy class name
int beginIndex;
if ((beginIndex = filename.lastIndexOf(File.separator)) != -1) {
filename = filename.substring(beginIndex + 1);
}
locals.__setitem__("__name__", new PyString(filename));
locals.__setitem__("zipfile", Py.java2py(zip));
InputStream file = zip.getInputStream(runit);
PyCode code;
try {
code = Py.compile(FileUtil.readBytes(file), "__run__", "exec");
} finally {
file.close();
}
Py.runCode(code, locals, locals);
} catch (java.io.IOException e) {
throw Py.IOError(e);
}
}
public static void main(String[] args) {
// Parse the command line options
CommandLineOptions opts = new CommandLineOptions();
if (!opts.parse(args)) {
if (opts.version) {
PySystemState.determinePlatform(System.getProperties());
System.err.println(InteractiveConsole.getDefaultBanner());
System.exit(0);
}
System.err.println(usage);
int exitcode = opts.help ? 0 : -1;
System.exit(exitcode);
}
// Setup the basic python system state from these options
PySystemState.initialize(PySystemState.getBaseProperties(), opts.properties, opts.argv);
if (opts.notice) {
System.err.println(InteractiveConsole.getDefaultBanner());
}
// Now create an interpreter
InteractiveConsole interp = null;
try {
String interpClass = PySystemState.registry.getProperty("python.console",
"org.python.util.InteractiveConsole");
interp = (InteractiveConsole) Class.forName(interpClass).newInstance();
} catch (Exception e) {
interp = new InteractiveConsole();
}
//System.err.println("interp");
PyModule mod = imp.addModule("__main__");
interp.setLocals(mod.__dict__);
//System.err.println("imp");
for (int i = 0; i < opts.warnoptions.size(); i++) {
String wopt = (String) opts.warnoptions.elementAt(i);
PySystemState.warnoptions.append(new PyString(wopt));
}
String msg = "";
if (Options.importSite) {
try {
imp.load("site");
if (opts.notice) {
PyObject builtins = Py.getSystemState().builtins;
boolean copyright = builtins.__finditem__("copyright") != null;
boolean credits = builtins.__finditem__("credits") != null;
boolean license = builtins.__finditem__("license") != null;
if (copyright) {
msg += "\"copyright\"";
if (credits && license)
msg += ", ";
else if (credits || license)
msg += " or ";
}
if (credits) {
msg += "\"credits\"";
if (license)
msg += " or ";
}
if (license)
msg += "\"license\"";
if (msg.length() > 0)
System.err.println("Type " + msg + " for more information.");
}
} catch (PyException pye) {
if (!Py.matchException(pye, Py.ImportError)) {
System.err.println("error importing site");
Py.printException(pye);
System.exit(-1);
}
}
}
if (opts.division != null) {
if ("old".equals(opts.division))
Options.divisionWarning = 0;
else if ("warn".equals(opts.division))
Options.divisionWarning = 1;
else if ("warnall".equals(opts.division))
Options.divisionWarning = 2;
else if ("new".equals(opts.division)) {
Options.Qnew = true;
interp.cflags.division = true;
}
}
// was there a filename on the command line?
if (opts.filename != null) {
String path = new java.io.File(opts.filename).getParent();
if (path == null)
path = "";
Py.getSystemState().path.insert(0, new PyString(path));
if (opts.jar) {
runJar(opts.filename);
} else if (opts.filename.equals("-")) {
try {
throw new RuntimeException("Can not run from <stdin> in internal PyDev version.");
// interp.locals.__setitem__(new PyString("__file__"),
// new PyString("<stdin>"));
// interp.execfile(System.in, "<stdin>");
} catch (Throwable t) {
Py.printException(t);
}
} else {
try {
interp.locals.__setitem__(new PyString("__file__"), new PyString(opts.filename));
interp.execfile(opts.filename);
} catch (Throwable t) {
Py.printException(t);
if (!opts.interactive) {
interp.cleanup();
System.exit(-1);
}
}
}
} else {
// if there was no file name on the command line, then "" is
// the first element on sys.path. This is here because if
// there /was/ a filename on the c.l., and say the -i option
// was given, sys.path[0] will have gotten filled in with the
// dir of the argument filename.
Py.getSystemState().path.insert(0, new PyString(""));
if (opts.command != null) {
try {
interp.exec(opts.command);
} catch (Throwable t) {
Py.printException(t);
}
}
}
if (opts.interactive) {
if (opts.encoding == null) {
opts.encoding = PySystemState.registry.getProperty("python.console.encoding", null);
}
if (opts.encoding != null) {
if (!Charset.isSupported(opts.encoding)) {
System.err
.println(opts.encoding
+ " is not a supported encoding on this JVM, so it can't be used in python.console.encoding.");
System.exit(1);
}
interp.cflags.encoding = opts.encoding;
}
try {
interp.interact(null);
} catch (Throwable t) {
Py.printException(t);
}
}
interp.cleanup();
if (opts.interactive) {
System.exit(0);
}
}
}
class CommandLineOptions {
public String filename;
public boolean jar, interactive, notice;
private boolean fixInteractive;
public boolean help, version;
public String[] argv;
public java.util.Properties properties;
public String command;
public java.util.Vector warnoptions = new java.util.Vector();
public String encoding;
public String division;
public CommandLineOptions() {
filename = null;
jar = fixInteractive = false;
interactive = notice = true;
properties = new java.util.Properties();
help = version = false;
}
public void setProperty(String key, String value) {
properties.put(key, value);
try {
System.setProperty(key, value);
} catch (SecurityException e) {
}
}
public boolean parse(String[] args) {
int index = 0;
while (index < args.length && args[index].startsWith("-")) {
String arg = args[index];
if (arg.equals("--help")) {
help = true;
return false;
} else if (arg.equals("--version")) {
version = true;
return false;
} else if (arg.equals("-")) {
if (!fixInteractive)
interactive = false;
filename = "-";
} else if (arg.equals("-i")) {
fixInteractive = true;
interactive = true;
} else if (arg.equals("-jar")) {
jar = true;
if (!fixInteractive)
interactive = false;
} else if (arg.equals("-v")) {
Options.verbose++;
} else if (arg.equals("-vv")) {
Options.verbose += 2;
} else if (arg.equals("-vvv")) {
Options.verbose += 3;
} else if (arg.equals("-S")) {
Options.importSite = false;
} else if (arg.equals("-c")) {
command = args[++index];
if (!fixInteractive)
interactive = false;
index++;
break;
} else if (arg.equals("-W")) {
warnoptions.addElement(args[++index]);
} else if (arg.equals("-E")) {
encoding = args[++index];
} else if (arg.startsWith("-D")) {
String key = null;
String value = null;
int equals = arg.indexOf("=");
if (equals == -1) {
String arg2 = args[++index];
key = arg.substring(2, arg.length());
value = arg2;
} else {
key = arg.substring(2, equals);
value = arg.substring(equals + 1, arg.length());
}
setProperty(key, value);
} else if (arg.startsWith("-Q")) {
if (arg.length() > 2)
division = arg.substring(2);
else
division = args[++index];
} else {
String opt = args[index];
if (opt.startsWith("--"))
opt = opt.substring(2);
else if (opt.startsWith("-"))
opt = opt.substring(1);
System.err.println("jython: illegal option -- " + opt);
return false;
}
index += 1;
}
notice = interactive;
if (filename == null && index < args.length && command == null) {
filename = args[index++];
if (!fixInteractive)
interactive = false;
notice = false;
}
if (command != null)
notice = false;
int n = args.length - index + 1;
argv = new String[n];
//new String[args.length-index+1];
if (filename != null)
argv[0] = filename;
else if (command != null)
argv[0] = "-c";
else
argv[0] = "";
for (int i = 1; i < n; i++, index++) {
argv[i] = args[index];
}
return true;
}
}